package com.tools.web.ali;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.tools.common.exception.NetRequestRuntimeException;
import com.tools.common.io.CharsetEnum;
import com.tools.common.object.Note;

/**
 * 支付宝授权登录的工具类实体
 * 请设置为单例使用。
 * */
@Note("支付宝授权登录的工具类实体。" +
        "请设置为单例使用")
public final class AlipayLoginBean {

    @Note("申请审核通过的应用持续的 ID")
    private final String appId;

    @Note("有 【auth_base】 和 【auth_user】 两个值。" +
            "【auth_base】: 用户登录后直接跳转重定向的接口。后面得到 access_token 不能获取用户信息。" +
            "【auth_user】: 用户登录后需要确认后才能跳转重定向的接口。后面得到 access_token 可以获取用户信息。" +
            "另外 【auth_user】 用户已经授权成功的情况下，再次访问授权链接授权，会出现没有授权确认页面，登录账户成功后直接跳转到授权回调地址页面。")
    private final String scope;

    @Note("用户授权登录成功后重定向至哪个接口地址")
    private final String redirectUri;

    @Note("用于发送请求的客户端实例对象")
    private final AlipayClient alipayClient;


    public AlipayLoginBean(String appId, String publicKey, String privateKey,
                           String redirectUri, String getaway, CharsetEnum charset,
                           String scope) {
        if(charset != CharsetEnum.UTF_8 && charset != CharsetEnum.GBK) {
            throw new IllegalArgumentException("字符集编码只能是 UTF-8 或者 GBK");
        }
        if(!"auth_user".equals(scope) && !"auth_base".equals(scope)) {
            throw new IllegalArgumentException("scope 的值只能是 auth_user 或者 auth_base");
        }
        this.alipayClient = new DefaultAlipayClient(getaway, appId, privateKey,
                "json", charset.getValue(), publicKey, "RSA2");
        this.appId = appId;
        this.scope = scope;
        this.redirectUri = redirectUri;
    }


    @Note("返回支付宝用于登录的 URL 给前端，最好以二维码的形式响应")
    public String getAliPayLoginURL() {
        return "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?" +
                "app_id=" + appId +
                "&scope=" + scope +
                "&redirect_uri=" + redirectUri;
    }


    @Note("用户授权登录后，跳转到这里，同时会携带一个 auth_code 参数用于给我们获取 access_token" +
            "auth_code 只能使用一次，1 天未被使用就会过期")
    public String getAlipayAccessToken(String authCode) {
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setCode(authCode);
        request.setGrantType("authorization_code");
        try {
            AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
            return response.isSuccess()
                    ? response.getAccessToken()
                    : null;
        } catch (AlipayApiException e) {
            throw new NetRequestRuntimeException(e);
        }
    }


    @Note("用 access_token 发起请求获取用户头像、昵称的信息")
    public AlipayUserInfoShareResponse getUserInfoByAccessToken(String accessToken) {
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        try {
             return alipayClient.execute(request, accessToken);
        } catch (AlipayApiException e) {
            throw new NetRequestRuntimeException(e);
        }
    }
}
